package io.shuttle.mbe.api

import io.shuttle.mbe.api.annotation.ChromeMinVersion
import io.shuttle.mbe.api.annotation.PromiseStyleMinVersion
import io.shuttle.mbe.api.types.Value1Function
import io.shuttle.mbe.api.types.VoidFunction
import io.shuttle.mbe.core.Promise

////////////////////
// Text to Speech
////////////////////
/**
 * Use the `Browser.tts` API to play synthesized text-to-speech (TTS). See also the related {@link ttsEngine} API, which allows an extension to implement a speech engine.
 *
 * Permissions: "tts"
 */
interface Tts {
    // Gets an array of all available voices.
    // @param  {voices} - Array of tts.TtsVoice objects representing the available voices for speech synthesis.
    @PromiseStyleMinVersion(101)
    fun getVoices(callback: Value1Function<List<TtsVoice>>? = null): Promise<List<TtsVoice>>

    // Checks whether the engine is currently speaking. On Mac OS X, the result is true whenever the system speech engine is speaking, even if the speech wasn't initiated by Chrome.
    // @param  {speaking} - True if speaking, false otherwise.
    @PromiseStyleMinVersion(101)
    fun isSpeaking(callback: Value1Function<Boolean>? = null): Promise<Boolean>

    // Pauses speech synthesis, potentially in the middle of an utterance. A call to resume or stop will un-pause speech.
    fun pause()

    // If speech was paused, resumes speaking where it left off.
    fun resume()

    // Speaks text using a text-to-speech engine.
    @PromiseStyleMinVersion(101)
    fun speak(
        // The text to speak, either plain text or a complete, well-formed SSML document. Speech engines that do not support SSML will strip away the tags and speak the text. The maximum length of the text is 32,768 characters.
        utterance: String,
        options: TtsOptions? = null,
        callback: VoidFunction? = null
    ): Promise<Void>

    // Stops any current speech and flushes the queue of any pending utterances. In addition, if speech was paused, it will now be un-paused for the next call to speak.
    fun stop()

    // Called when the list of tts.TtsVoice that would be returned by getVoices has changed.
    @ChromeMinVersion(124)
    val onVoicesChanged: Events.Event<VoidFunction>

    @ChromeMinVersion(54)
    enum class EventType {
        start,
        end,
        word,
        sentence,
        marker,
        interrupted,
        cancelled,
        error,
        pause,
        resume
    }

    // An event from the TTS engine to communicate the status of an utterance.
    data class TtsEvent(
        // The index of the current character in the utterance. For word events, the event fires at the end of one word and before the beginning of the next. The charIndex represents a point in the text at the beginning of the next word to be spoken.
        var charIndex: Number?,
        // The error description, if the event type is error.
        var errorMessage: String?,
        // The length of the next part of the utterance. For example, in a word event, this is the length of the word which will be spoken next. It will be set to -1 if not set by the speech engine.
        @ChromeMinVersion(74)
        var length: Number?,
        // The type can be start as soon as speech has started, word when a word boundary is reached, sentence when a sentence boundary is reached, marker when an SSML mark element is reached, end when the end of the utterance is reached, interrupted when the utterance is stopped or interrupted before reaching the end, cancelled when it's removed from the queue before ever being synthesized, or error when any other error occurs. When pausing speech, a pause event is fired if a particular utterance is paused in the middle, and resume if an utterance resumes speech. Note that pause and resume events may not fire if speech is paused in-between utterances.
        var type: EventType
    )

    @ChromeMinVersion(77)
    data class TtsOptions(
        // The TTS event types that you are interested in listening to. If missing, all event types may be sent.
        var desiredEventTypes: List<String>?,
        // If true, enqueues this utterance if TTS is already in progress. If false (the default), interrupts any current speech and flushes the speech queue before speaking this new utterance.
        var enqueue: Boolean?,
        // The extension ID of the speech engine to use, if known.
        var extensionId: String?,
        // Gender of voice for synthesized speech.
        @Deprecated(
            "Deprecated since Chrome 77",
            replaceWith = ReplaceWith("Gender is deprecated and will be ignored.")
        )
        var gender: VoiceGender?,
        // The language to be used for synthesis, in the form language-region. Examples: 'en', 'en-US', 'en-GB', 'zh-CN'.
        var lang: String?,
        // Speaking pitch between 0 and 2 inclusive, with 0 being lowest and 2 being highest. 1.0 corresponds to a voice's default pitch.
        var pitch: Number?,
        // Speaking rate relative to the default rate for this voice. 1.0 is the default rate, normally around 180 to 220 words per minute. 2.0 is twice as fast, and 0.5 is half as fast. Values below 0.1 or above 10.0 are strictly disallowed, but many voices will constrain the minimum and maximum rates further—for example a particular voice may not actually speak faster than 3 times normal even if you specify a value larger than 3.0.
        var rate: Number?,
        // The TTS event types the voice must support.
        var requiredEventTypes: List<String>?,
        // The name of the voice to use for synthesis. If empty, uses any available voice.
        var voiceName: String?,
        // Speaking volume between 0 and 1 inclusive, with 0 being lowest and 1 being highest, with a default of 1.0.
        var volume: Number?,
        // This function is called with events that occur in the process of speaking the utterance.
        // @callback event - The update event from the text-to-speech engine indicating the status of this utterance.
        var onEvent: Value1Function<TtsEvent>? = null
    )

    // A description of a voice available for speech synthesis.
    data class TtsVoice(
        // All of the callback event types that this voice is capable of sending.
        var eventTypes: List<EventType>?,
        // The ID of the extension providing this voice.
        var extensionId: String?,
        // Gender of voice for synthesized speech.
        @Deprecated(
            "Deprecated since Chrome 77",
            replaceWith = ReplaceWith("Gender is deprecated and will be ignored.")
        )
        var gender: VoiceGender?,
        // // The language to be used for synthesis, in the form language-region. Examples: 'en', 'en-US', 'en-GB', 'zh-CN'.
        var lang: String?,
        // If true, the synthesis engine is a remote network resource. It may be higher latency and may incur bandwidth costs.
        var remote: Boolean?,
        // The name of the voice to use for synthesis. If empty, uses any available voice.
        var voiceName: String?,
    )

    @ChromeMinVersion(54)
    @Deprecated(
        "Deprecated since Chrome 70",
        replaceWith = ReplaceWith("Gender is deprecated and is ignored.")
    )
    enum class VoiceGender {
        male,
        female
    }
}